﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Noris.Tools.TraceVisualiser.Parser
{
    #region class Lexer : třída, která vkládá do položek parsovaných segmentů informace o klíčových slovech
    /// <summary>
    /// Lexer : třída, která vkládá do položek parsovaných segmentů informace o klíčových slovech
    /// </summary>
    public class Lexer : IDisposable
    {
        private Lexer() { }
        void IDisposable.Dispose() { }
        /// <summary>
        /// Do každé položky v předaném soupisu segmentů vloží informaci o keyword
        /// </summary>
        /// <param name="segments"></param>
        public static void Lexe(IEnumerable<ParserSegment> segments)
        {
            using (Lexer lexer = new Lexer())
            {
                Dictionary<string, object> keywords = SqlKeywords(); // new List<string>("SELECT,FROM,JOIN,WHERE,ON,ALL,TOP,DISTINCT,GROUP BY,ORDER BY,UNION,IN,UPDATE,SET,DELETE,INSERT,CREATE,DROP,ALTER,TABLE,INDEX,CONSTRAINT,PRIMARY KEY,IDENTITY".Split(','));
                foreach (ParserSegment segment in segments)
                {
                    lexer.Lexing(segment, keywords);
                }
            }
        }
        /// <summary>
        /// Vytvoří a vrátí seznam Keywords pro jazyk T-SQL
        /// </summary>
        /// <returns></returns>
        public static Dictionary<string, object> SqlKeywords()
        {
            #region Text of keywords
            string keywords = @"
ADD
 EXISTS
 PRECISION
 
ALL
 EXIT
 PRIMARY
 
ALTER
 EXTERNAL
 PRINT
 
AND
 FETCH
 PROC
 
ANY
 FILE
 PROCEDURE
 
AS
 FILLFACTOR
 PUBLIC
 
ASC
 FOR
 RAISERROR
 
AUTHORIZATION
 FOREIGN
 READ
 
BACKUP
 FREETEXT
 READTEXT
 
BEGIN
 FREETEXTTABLE
 RECONFIGURE
 
BETWEEN
 FROM
 REFERENCES
 
BREAK
 FULL
 REPLICATION
 
BROWSE
 FUNCTION
 RESTORE
 
BULK
 GOTO
 RESTRICT
 
BY
 GRANT
 RETURN
 
CASCADE
 GROUP
 REVERT
 
CASE
 HAVING
 REVOKE
 
CHECK
 HOLDLOCK
 RIGHT
 
CHECKPOINT
 IDENTITY
 ROLLBACK
 
CLOSE
 IDENTITY_INSERT
 ROWCOUNT
 
CLUSTERED
 IDENTITYCOL
 ROWGUIDCOL
 
COALESCE
 IF
 RULE
 
COLLATE
 IN
 SAVE
 
COLUMN
 INDEX
 SCHEMA
 
COMMIT
 INNER
 SECURITYAUDIT
 
COMPUTE
 INSERT
 SELECT
 
CONSTRAINT
 INTERSECT
 SESSION_USER
 
CONTAINS
 INTO
 SET
 
CONTAINSTABLE
 IS
 SETUSER
 
CONTINUE
 JOIN
 SHUTDOWN
 
CONVERT
 KEY
 SOME
 
CREATE
 KILL
 STATISTICS
 
CROSS
 LEFT
 SYSTEM_USER
 
CURRENT
 LIKE
 TABLE
 
CURRENT_DATE
 LINENO
 TABLESAMPLE
 
CURRENT_TIME
 LOAD
 TEXTSIZE
 
CURRENT_TIMESTAMP
 MERGE
 THEN
 
CURRENT_USER
 NATIONAL
 TO
 
CURSOR
 NOCHECK 
 TOP
 
DATABASE
 NONCLUSTERED
 TRAN
 
DBCC
 NOT
 TRANSACTION
 
DEALLOCATE
 NULL
 TRIGGER
 
DECLARE
 NULLIF
 TRUNCATE
 
DEFAULT
 OF
 TSEQUAL
 
DELETE
 OFF
 UNION
 
DENY
 OFFSETS
 UNIQUE
 
DESC
 ON
 UNPIVOT
 
DISK
 OPEN
 UPDATE
 
DISTINCT
 OPENDATASOURCE
 UPDATETEXT
 
DISTRIBUTED
 OPENQUERY
 USE
 
DOUBLE
 OPENROWSET
 USER
 
DROP
 OPENXML
 VALUES
 
DUMP
 OPTION
 VARYING
 
ELSE
 OR
 VIEW
 
END
 ORDER
 WAITFOR
 
ERRLVL
 OUTER
 WHEN
 
ESCAPE
 OVER
 WHERE
 
EXCEPT
 PERCENT
 WHILE
 
EXEC
 PIVOT
 WITH
 
EXECUTE
 PLAN
 WRITETEXT
 

";
            #endregion

            string[] keywordList = keywords.Split('\r', '\r');
            Dictionary<string, object> result = new Dictionary<string, object>();
            foreach (string kw in keywordList)
            {
                string keyword = kw.Trim(' ', '\t', '\n', '\r').ToUpper();
                if (keyword.Length > 0 && !result.ContainsKey(keyword))
                    result.Add(keyword, null);
            }
            return result;
        }
        private void Lexing(ParserSegment segment, Dictionary<string, object> keywords)
        {
            foreach (ParserSegmentValue value in segment.Values)
            {
                if (value.ValueType == ParserSegmentValueType.Text)
                {
                    if (keywords.ContainsKey(value.Content.ToUpper()))
                        value.ValueName = "Keyword";
                }
                if (value.HasInnerSegment)
                    this.Lexing(value.InnerSegment, keywords);
            }
        }
    }
    #endregion
}
